%% -*- coding: utf-8 -*-

%% @doc てんぷら宣言の処理
%%
-module(templ_decl).
-export([parse/1]).

-define(WSPACE(C),   ((C=:=$ ) orelse (C=:=$\t))).
-define(ALPHABET(C), (((C>=$A) andalso (C=<$Z)) orelse ((C>=$a) andalso (C=<$z)))).
-define(DIGIT(C),    ((C>=$0) andalso (C=<$9))).


parse([${,$*,$!|Cs]) ->
    parse_name(Cs, [], 4);
parse(_Input) ->
	%throw({{templ_decl,einval}, {Input,0}}).
	none.

parse_name([$*,$}|Cs], PL, N) -> 
	parse_endl(Cs, PL, N+2);
parse_name([C|Cs], PL, N) when ?WSPACE(C) -> 
	parse_name(Cs, PL, N+1);
parse_name([C|Cs], PL, N) when ?ALPHABET(C) ->
	parse_name_body(Cs, PL, N+1, [C]);
parse_name(Input,  _, N) ->
	throw({{templ_decl,einval}, {N,Input}}).

parse_name_body([C|Cs], PL, N, CStack) 
  when ?ALPHABET(C) orelse ?DIGIT(C) ->
	parse_name_body(Cs, PL, N+1, [C|CStack]);
parse_name_body(Input, PL, N, CStack) ->
	parse_eq(Input, PL, N, lists:reverse(CStack)).

parse_eq([C|Cs],  PL, N, Name) when ?WSPACE(C) -> 
	parse_eq(Cs, PL, N+1, Name);
parse_eq([$=|Cs], PL, N, Name) ->
	parse_value(Cs, PL, N+1, Name);
parse_eq(Input,  _, N, _) ->
	throw({{templ_decl,einval}, {N,Input}}).

parse_value([C|Cs],  PL, N, Name) when ?WSPACE(C) -> 
	parse_value(Cs, PL, N+1, Name);
parse_value([$"|Cs], PL, N, Name) -> % "
	parse_string(Cs, PL, N+1, Name, []);
parse_value(Input, _, N, _) ->
	throw({{templ_decl,einval}, {N,Input}}).

parse_string([$"|Cs], PL, N, Name, CStack) -> % "
	parse_spc(Cs, [{list_to_atom(Name),lists:reverse(CStack)}|PL], N+1);
parse_string([$\n|_]=Input, _, N, _, _) ->
	throw({{templ_decl,einval}, {N,Input}});
parse_string([], _, N, _, _) ->
	throw({{templ_decl,einval}, {N,[]}});
parse_string([C|Cs], PL, N, Name, CStack) ->
	parse_string(Cs, PL, N+1, Name, [C|CStack]).

parse_spc([$*,$}|Cs], PL, N) -> 
	parse_endl(Cs, PL, N+2);
parse_spc([C|Cs], PL, N) when ?WSPACE(C) ->
	parse_name(Cs, PL, N+1);
parse_spc(Input, _, N) ->
	throw({{templ_decl,einval}, {N,Input}}).

parse_endl([$\n|Cs], PL, _N) ->
	{PL,Cs};
parse_endl([], PL, _N) ->
	{PL,[]};
parse_endl([C|Cs], PL, N) when ?WSPACE(C) -> 
	parse_endl(Cs, PL, N+1);
parse_endl(Input, _, N) ->
	throw({{templ_decl,einval}, {N,Input}}).
